package com.zbycorp.generatecode.ui;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ExceptionUtil;
import com.zbycorp.generatecode.dict.GlobalDict;
import com.zbycorp.generatecode.entity.TableInfo;
import com.zbycorp.generatecode.entity.Template;
import com.zbycorp.generatecode.factory.CellEditorFactory;
import com.zbycorp.generatecode.service.CodeGenerateService;
import com.zbycorp.generatecode.service.SettingsStorageService;
import com.zbycorp.generatecode.service.TableInfoSettingsService;
import com.zbycorp.generatecode.ui.base.TableModel;
import com.zbycorp.generatecode.utils.CacheDataUtil;
import com.zbycorp.generatecode.utils.NameUtils;
import com.zbycorp.generatecode.utils.StringUtil;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author YCL
 * @date 2023/3/27
 */
public class SelectSavePath extends DialogWrapper {

    /**
     * 主面板
     */
    private JPanel mainPanel;
    private JPanel packagePanel;
    private JPanel tablePanel;
    /**
     * 包字段
     */
    private JTextField definedPackageField;
    /**
     * 包选择按钮
     */
    private JButton packageChooseButton;
    private JTextField domainPackageField;
    private JTextField authorField;
    private JTextField tablePrefixField;
    /**
     * 表信息对象
     */
    private TableInfo tableInfo;
    private Project project;
    private TableModel tableModel;
    private List<Template> templateList = new ArrayList<>();
    private CodeGenerateService codeGenerateService;

    @Override
    protected @Nullable JComponent createCenterPanel() {
        return this.mainPanel;
    }

    public SelectSavePath(@Nullable Project project) {
        super(project);
        this.project = project;

        initPanel();
        initEvent();
        init();
    }

    /**
     * 初始化方法
     */
    private void initPanel() {
        this.packagePanel = new JPanel(new GridLayout(-1, 2));
        this.mainPanel.add(this.packagePanel, BorderLayout.CENTER);

        String author = SettingsStorageService.getSettingStorage(project).getAuthor();
        if (StringUtil.isEmpty(author)) {
            author = System.getProperty("user.name");
        }
        authorField.setText(author);
        definedPackageField.setText(SettingsStorageService.getSettingStorage(project).getDefinedPackage());
        domainPackageField.setText(SettingsStorageService.getSettingStorage(project).getDomainPackage());
        tablePrefixField.setText(SettingsStorageService.getSettingStorage(project).getTablePrefix());


        this.tableInfo = TableInfoSettingsService.getInstance(project).getTableInfo(project, CacheDataUtil.getInstance().getSelectDbTable());
        setTitle("表：" + this.tableInfo.getObj().getName());
        this.tableModel = new TableModel(project, this.tableInfo, this.templateList);
        JBTable table = new JBTable(tableModel);
        this.tableModel.setTable(table);

        TableColumn moduleColumn = table.getColumn("Module");
        moduleColumn.setPreferredWidth(200);
        TableColumn classColumn = table.getColumn("Class");
        classColumn.setPreferredWidth(300);
        TableColumn pathColumn = table.getColumn("Package");
        pathColumn.setPreferredWidth(500);
        pathColumn.setCellEditor(CellEditorFactory.createTextFieldEditor());

        final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(table);
        this.tablePanel.add(decorator.createPanel(), BorderLayout.CENTER);

        this.mainPanel.add(this.tablePanel);
        this.mainPanel.setMinimumSize(new Dimension(1000, 400));

    }

    private void initEvent() {
        try {
            Class<?> cls = Class.forName("com.intellij.ide.util.PackageChooserDialog");
            //添加包选择事件
            packageChooseButton.addActionListener(e -> {
                try {
                    Constructor<?> constructor = cls.getConstructor(String.class, Project.class);
                    Object dialog = constructor.newInstance("Package Chooser", project);
                    // 显示窗口
                    Method showMethod = cls.getMethod("show");
                    showMethod.invoke(dialog);
                    // 获取选中的包名
                    Method getSelectedPackageMethod = cls.getMethod("getSelectedPackage");
                    Object psiPackage = getSelectedPackageMethod.invoke(dialog);
                    if (psiPackage != null) {
                        Method getQualifiedNameMethod = psiPackage.getClass().getMethod("getQualifiedName");
                        String packageName = (String) getQualifiedNameMethod.invoke(psiPackage);
                        definedPackageField.setText(packageName);
                        refreshPackage();
                    }
                } catch (NoSuchMethodException | IllegalAccessException | InstantiationException |
                         InvocationTargetException e1) {
                    ExceptionUtil.rethrow(e1);
                }
            });
            definedPackageField.addKeyListener(new KeyAdapter() {
                @Override
                public void keyReleased(KeyEvent e) {
                    refreshPackage();
                }
            });
            domainPackageField.addKeyListener(new KeyAdapter() {
                @Override
                public void keyReleased(KeyEvent e) {
                    refreshPackage();
                }
            });
            tablePrefixField.addKeyListener(new KeyAdapter() {
                @Override
                public void keyReleased(KeyEvent e) {
                    refreshPackage();
                }
            });
        } catch (ClassNotFoundException e) {
            // 没有PackageChooserDialog，并非支持Java的IDE，禁用相关UI组件
            definedPackageField.setEnabled(false);
            packageChooseButton.setEnabled(false);
        }
    }

    private void refreshPackage() {
        String tablePrefix = tablePrefixField.getText();
        SettingsStorageService.getSettingStorage(project).setTablePrefix(tablePrefixField.getText());
        String tableName = NameUtils.getInstance().getClassName(tableInfo.getObj().getName().replaceFirst("^" + tablePrefix, ""));
        // 表名去掉前缀-首字母大写
        tableInfo.setName(tableName);

        String definedPackageFieldText = definedPackageField.getText();
        String domainPackageFieldText = domainPackageField.getText();
        SettingsStorageService.getSettingStorage(project).setDefinedPackage(definedPackageFieldText);
        SettingsStorageService.getSettingStorage(project).setDomainPackage(domainPackageFieldText);
        templateList.forEach(item -> {
            item.setDefinedPackage(definedPackageFieldText);
            item.setDomainPackage(domainPackageFieldText);

            if ("entity".equals(item.getDefaultName())) {
                item.setClassName(tableName);
            } else {
                item.setClassName(tableName + item.getDefaultName());
            }

            String savePackage = "";
            if (!StringUtil.isEmpty(item.getDefinedPackage())) {
                savePackage = String.format("%s.%s", item.getDefinedPackage(), item.getDefaultPackage());
                if (!StringUtil.isEmpty(item.getDomainPackage())) {
                    savePackage = String.format("%s.%s", savePackage, item.getDomainPackage());
                }
            }
            item.setSavePackage(savePackage);
        });
        tableModel.initTableData();
    }

    @Override
    protected void doOKAction() {
        onOK();
        super.doOKAction();
    }

    /**
     * 确认按钮回调事件
     */
    private void onOK() {
        // 如果选择的模板是空的
        if (StringUtil.isEmpty(definedPackageField.getText())) {
            Messages.showWarningDialog("请选择definedPackage", GlobalDict.TITLE_INFO);
            return;
        }

        SettingsStorageService.getSettingStorage(project).setAuthor(authorField.getText());

        this.codeGenerateService = CodeGenerateService.getInstance(project);
        // 生成代码
        this.codeGenerateService.generate(project, tableInfo, this.templateList);
    }

}
